/*
 * $Id:
 *
 * Copyright (C) 2011 Refiner Inc.
 * All right reserved
 *
 *============================================================
 * +rVPN Stack : AppIF (Application Interface)
 *============================================================
 * abstract: This module provides rvs socket functions
 * author  : MURATA
 * history :
 *
 */

#ifndef _RVS_SOCKET_H_
#define _RVS_SOCKET_H_

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

#ifdef __cplusplus
extern "C"{
#endif

#define RVSA_ERRBASE    0x1000000
#define	RVSA_EAGAIN     (RVSA_ERRBASE+EAGAIN)
#define	RVSA_EIO        (RVSA_ERRBASE+EIO)
#define	RVSA_ENOTINIT   (RVSA_ERRBASE+200)
#define RVSA_EOF        (RVSA_ERRBASE+201)


/* インタフェース種別 */
enum {
    VIF_NONE=0,     /* 何も割り当たっていない */
    VIF_CENTER,		/* センターVPN用 */
    VIF_APPIF,	    /* アプリケーション通信用 */
    VIF_TUN_P2PS,	/* P2Pサーバトンネル端点 */
    VIF_TUN_P2PC,	/* P2Pクライアントトンネル端点 */
    VIF_NUMKIND
};

/* ルーティング種別 */
enum {
    VIFRT_NONE=0,	    /* ルーティング情報なし */
    VIFRT_SRC=0x01,	    /* ソースルーティング(この時、VIFのroute=NULL) */
    VIFRT_DEST=0x02,    /* 宛先ルーティング */
    VIFRT_BOTH=(VIFRT_SRC|VIFRT_DEST)
};

/* rvs_ioctl パラメータ */
#define VPNMODE 0x5470
#define MODE_USEVPN  1
#define MODE_NONVPN  2

#ifdef NO_THREADS
extern int rvs_errno;
#define rvs_set_errno(e)  { rvs_errno=(e); }
#else
extern int __rvs_error(void);
#define rvs_errno  (__rvs_error())
extern void  rvs_set_errno(int err);
#endif

/* rvs_api_init - App I/Fの初期化 */
int rvs_api_init(struct sockaddr* addr);

/* rvs_api_end - App I/Fの終了 */
void rvs_api_end(void);

/* ソケットの生成 */
int rvs_socket(int domain, int type, int protocol);

/* ソケットのクローズ */
int rvs_close(int fd);

/* ソケットのBind */
int rvs_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);

/* ソケットの接続 */
int rvs_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);

/* 接続を待つ */
int rvs_listen(int sockfd, int backlog);

/* 接続を受ける */
int rvs_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

/* メッセージ送信 */
int rvs_sendto(int s, const void *buf, size_t len, int flags,
                      const struct sockaddr *to, socklen_t tolen);

/* メッセージ受信 */
int rvs_recvfrom(int s, void *buf, size_t len, int flags,
                        struct sockaddr *from, socklen_t *fromlen);

/* メッセージ送信 */
int rvs_send(int s, const void *buf, size_t len, int flags);
static inline int rvs_write(int s, const void *buf, size_t len)
{
    return rvs_send(s, buf, len, 0);
}


/* メッセージ受信 */
int rvs_recv(int s, void *buf, size_t len, int flags);
static inline int rvs_read(int s, void *buf, size_t len)
{
    return rvs_recv(s, buf, len, 0);
}

/* オプションの設定 */
int rvs_setsockopt(int s, int level, int optname,
                          const void *optval, socklen_t optlen);

/* オプションの取得 */
int rvs_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);

/* ソケットの名前を取得 */
int rvs_getsockname(int s, struct sockaddr *name, socklen_t *namelen);

/* ソケットデバイス制御 */
int rvs_ioctl(int s, int request, void *argp);

/* ソケットを操作する */
int rvs_fcntl(int fd, int cmd,...);

/* ソケットのI/O同期 */
int rvs_select(int nfds, fd_set *readfds, fd_set *writefds, 
           fd_set *exceptfds, struct timeval *timeout);

/* OSディスクリプタとの同期I/O */
int rvs_select_multi(int rvnfds, fd_set *rvreadfds, 
           fd_set *rvwritefds, fd_set *rvexceptfds, 
           int nfds, fd_set *readfds, fd_set *writefds, 
           fd_set *exceptfds, struct timeval *timeout);

/* ソケットの遮断 */
int rvs_shutdown(int s , int how );

/* ローカルI/Fのアドレスを取得する */
int rvs_getlocalif(int type, struct sockaddr *addr, socklen_t *addrlen);

/* 発信元と宛先のアドレスより対応する仮想インターフェースを取得する */
int rvs_get_vifroute( const struct sockaddr *addr, const struct sockaddr *daddr);

#ifdef __cplusplus
}
#endif

#endif /* _RVS_SOCKET_H_ */
